#pragma once
#include "Comm.h"
#include "StdList.h"
#include "ThreadLock.h"

namespace COMM
{
	template<class T, class valueType=T>
	class ListReleaser
	{
	public:
		virtual ~ListReleaser(){}
		virtual void Release(){ delete this;}
		virtual void Delete(T& value){}
		virtual bool Compare(T& item, const valueType& value){ MYLIB_ASSERT(!"Method Not Implement!");return false;}
	};

	template<class T>
	class ValueEqualListReleaser : public ListReleaser<T>
	{
	public:
		virtual void Delete(T& value){}
		virtual bool Compare(T& item, const T& value){ return (item==value);}
	};

	template<class T, class valueType=T>
	class CommonListReleaser : public ListReleaser<T,valueType>
	{
	public:
		virtual void Delete(T& item){ if(NULL!=item){ delete item;} }
	};	

	template<class T, class valueType=T>
	class CustomListReleaser : public ListReleaser<T,valueType>
	{
	public:
		virtual void Delete(T& item){ if(NULL!=item){ item->Release();} }
	};	


	// MT-Safe
	//
	template<class T, class LOCK=ThreadLock, class valueType=T >
	class List
	{	
		MYLIB_NONCOPIED_CLASS(List);
	public:
		List(ListReleaser<T,valueType>* releaser=NULL)
			:m_releaser((NULL==releaser)?(new CommonListReleaser<T,valueType>()):releaser)
		{ MYLIB_ASSERT_NOTNULL(m_releaser);}
		virtual ~List(){ this->Clear(); delete m_releaser; m_releaser=NULL;};
		stdlist<T>& list(){ return m_list;}
		typename stdlist<T>::iterator begin(){return m_list.begin();}
		typename stdlist<T>::iterator end(){return m_list.end();}
		ThreadNullLock* Locker(){ return &m_lock;};
		int Count(){ ThreadLockGuard guard(&m_lock); return m_list.size();}
		T& At(int index){ ThreadLockGuard guard(&m_lock); return m_list.at(index);}
		T& operator[](int index){ return this->At(index); }
		List& operator<<(const T& item){ ThreadLockGuard guard(&m_lock); return this->Append(item,false); }
		List& Append(const T& item, bool front=false)
		{ 
			ThreadLockGuard guard(&m_lock); 
			if(front)
				m_list.push_front(item);
			else
				m_list.push_back(item);

			return *this;
		}
		
		bool Insert(const T& item, const valueType& value)
		{ 
			ThreadLockGuard guard(&m_lock); 
			typename stdlist<T>::iterator itor = Find(value);
			if(itor == m_list.end())
				return false;
			m_list.insert(itor,item);
			return true;
		}

		bool Fetch(T& item, const valueType& value)
		{
			ThreadLockGuard guard(&m_lock); 
			typename stdlist<T>::iterator itor = Find(value);
			if(itor == m_list.end())
				return false;
			item = *itor;
			return true;
		}

		bool Peek(T& item, bool front=true, bool remove=false)
		{
			ThreadLockGuard guard(&m_lock); 
			typename stdlist<T>::iterator itor = m_list.begin();
			if(itor == m_list.end())
				return false;
			if(!front)
			{
				itor = m_list.end();
				--itor;
			}
			item = *itor;
			if(remove)
				m_list.erase(itor);
			return true;
		}

		bool Pop(T& item, bool front=true)
		{
			return Peek(item,front,true);
		}
		
		bool Remove(const valueType& value, bool del=true)
		{ 
			ThreadLockGuard guard(&m_lock); 
			typename stdlist<T>::iterator itor = Find(value);
			if(itor == m_list.end())
				return false;
			if(del)
				m_releaser->Delete(*itor);
			m_list.erase(itor);
			return true;
		}

		void Clear()
		{ 
			ThreadLockGuard guard(&m_lock); 
			for(typename stdlist<T>::iterator itor=m_list.begin();itor!=m_list.end();itor++)
			{
				m_releaser->Delete(*itor);
			}
			m_list.clear();
		}

		bool Exist(const valueType& value)
		{ 
			ThreadLockGuard guard(&m_lock); 
			return (m_list.end() != Find(value));
		}

		typename stdlist<T>::iterator Find(const valueType& value)
		{
			ThreadLockGuard guard(&m_lock); 
			for (typename stdlist<T>::iterator itor=m_list.begin();itor!=m_list.end();itor++)
			{
				if(m_releaser->Compare(*itor,value))
					return itor;
			}
			return m_list.end();
		}

	private:
		LOCK m_lock;
		ListReleaser<T,valueType>* m_releaser;
		stdlist<T> m_list;
	};
}





